package test;

import org.mozilla.jrex.* ;
import org.mozilla.jrex.ui.* ;
import org.mozilla.jrex.window.* ;
import org.mozilla.jrex.navigation.* ;
import org.mozilla.jrex.event.progress.* ;
import org.w3c.dom.* ;
import java.lang.Exception.* ;
import javax.swing.*;
import java.net.*; 
import java.util.Vector;

import org.apache.commons.validator.*;

public class Render  implements org.mozilla.jrex.event.progress.ProgressListener {

	String url ;		// The page to be processed.

	// These variables can be used in subclasses and are created from
	// url.  baseURL can be used to construct the absolute URL of the
	// relative URL's in the page.  hostBase is just the http://host.com/
	// part of the URL and can be used to construct the full URL of
	// URLs in the page that are site relative, e.g., "/xyzzy.jpg".
	// Variable host is set to the host part of url, e.g., host.com.

	String baseURL ;
	String hostBase ;
	String host ;

	// The JRexCanvas is the main browser component.  The WebNavigator
	// is used to access the DOM.

	JRexCanvas canvas = null ;
	WebNavigation navigation = null ;

	// An event handler sets "done" to true when the document is loaded.

	boolean done = false ;

	/**
	      Create a Render object with a target URL.
	 */

	public Render(String URL) {
		url = URL ;
	}

	/**  Load the given URL in Gecko.  When the page is loaded, 
	recurse on the DOM and call doElement()/doTagEnd() for
	each Element node.  Execution can hang if the page causes a 
	window to be popped up.  Return false on error.
	 */

	public boolean parsePage() {

		// Parse the URL and build baseURL and hostURL for use by doElement()
		// and doTagEnd().

		URI uri = null ;
		try {
			uri = new URI(url) ;
		}
		catch(Exception e) {
			System.out.println(e) ;
			return false ;
		}

		String path = uri.getPath() ;
		baseURL = "http://" + uri.getHost() + path + "/" ;
		hostBase = "http://" + uri.getHost() ;
		host = uri.getHost() ;

		// Start up JRex/Gecko.

		try {
			JRexFactory.getInstance().startEngine();
		} 
		catch (Exception e) {
			System.err.println("Unable to start up JRex Engine.");
			e.printStackTrace();
			return false ;
		}

		// Get a window manager and put the browser in a Swing frame.
		// Based on Dietrich Kappe's code.

		JRexWindowManager winManager=(JRexWindowManager)
		JRexFactory.getInstance().getImplInstance(JRexFactory.WINDOW_MANAGER);
		winManager.create(JRexWindowManager.SINGLE_WINDOW_MODE);
		JPanel panel = new JPanel();
		JFrame frame = new JFrame();
		frame.getContentPane().add(panel);
		winManager.init(panel);

		// Get the JRexCanvas, set Render to handle progress events so
		// we can determine when the page is loaded, and get the 
		// WebNavigator object.

		canvas = (JRexCanvas) winManager.getBrowserForParent(panel);
		canvas.addProgressListener(this) ;
		navigation = canvas.getNavigator() ;

		// Load and process the page.

		try {
			navigation.loadURI(url, WebNavigationConstants.LOAD_FLAGS_NONE, 
					null, null, null);

			// Swing magic.

			/*			frame.setSize(640, 480);
			frame.setVisible(false);
			 */
			// Check if the DOM has loaded every two seconds.

			while(!done) {
				Thread.sleep(2000) ;
			}

			// Get the DOM and recurse on its nodes.

			Document doc = navigation.getDocument() ;
			Element ex = doc.getDocumentElement() ;
			doTree((Node) ex) ;
		}
		catch(Exception e) {
			System.out.println("Trouble walking DOM:  " + e) ;
			return false ;
		}

		return true ;
	}

	/**
    Recurse the DOM starting with Node node.  For each Node of
    type Element, call doElement() with it and recurse over its
    children.  The Elements refer to the HTML tags, and the children
    are tags contained inside the parent tag.
	 */

	public void doTree(Node node) {
		// Visit tag.

		if (node instanceof Element){
			Element element = (Element)node;


			try {
				doElement(element) ;
			} catch (URISyntaxException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			// Visit all the children, i.e., tags contained in this tag.

			NodeList nl = element.getChildNodes() ;
			if(nl == null) return ;
			int num = nl.getLength() ;
			for(int i=0; i<num; i++)
				doTree(nl.item(i)) ;
		}

		// Process the end of this tag.

		//doTagEnd(element) ;

	}

	/**
    check is this element is a script element. If it is, print it.
	 * @throws URISyntaxException 
	 */

	public void doElement(Element elem) throws URISyntaxException {

		if (elem.getTagName().equals("SCRIPT")){
			System.out.println("<" + elem.getTagName() + ">") ;
			return;
		}

		AttrTable attrTable = new AttrTable().getInstance();
		EventTable eventTable = new EventTable().getInstance();

		Vector<String> table = attrTable.getTable();
		table.addAll(eventTable.getTable());

		if (elem.hasAttributes()){
			
			for (String attr : table){
				if (elem.hasAttribute(attr)){
					System.out.println(elem.getAttribute(attr));
					break;
				}
				/*				String src = getSourceUrl(elem.getAttribute("SRC"));
				if (src.endsWith("js"))
					System.out.println("<" + elem.getTagName() + ">" + " SRC=" + elem.getAttribute("SRC")) ;
				return;
			}*/
			}
		}

	}

	public String getSourceUrl(String str) throws URISyntaxException{

		if  (str.startsWith("//")){
			str = str.substring(2);
			str = baseURL+str;
		}
		if (str.startsWith("/")){
			str = str.substring(1);
			str = baseURL+str;
		}
		return (new URI(str).getPath());

	}

	/**
    Simple doTagEnd() to print the closing tag of the Element.
    Override to do something real.
	 */

	public void doTagEnd(Element element) {
		System.out.println("</" + element.getTagName() + ">") ;      
	}

//	org.mozilla.jrex.event.progress.ProgressListener methods.
//	onStateChange() seems the best place to watch for the
//	completion of the loading of the DOM.

	/** Noop */
	public void onLinkStatusChange(ProgressEvent event) {   }
	/** Noop */
	public void onLocationChange(ProgressEvent event) {   }
	/** Noop */
	public void onProgressChange(ProgressEvent event) {   }
	/** Noop */
	public void onSecurityChange(ProgressEvent event) {   }

	/** onStateChange is invoked several times when DOM loading is
     complete.  Set the done flag the first time.
	 */

	public void onStateChange(ProgressEvent event) {
		if(!event.isLoadingDocument()) {
			if(done) return ;
			done = true ;
		}
	}

	/** Noop */
	public void onStatusChange(ProgressEvent event) {   }

	/**
	 * Main: Render [url].  Run JRex on the given page, wait for the page to load, and 
	 *traverse the DOM, printing tag names only.
	 */
	public static void main(String[] args) {
		System.setProperty("jrex.gre.path","C:/jrex/jrex_gre");
		System.setProperty("jrex.dom.enable","true");
		String url ="http://www.cnn.com" ;
		if(args.length == 1) url = args[0] ;
		Render p = new Render(url) ;
		p.parsePage() ;
		System.exit(0) ;
	}

}
